package com.example.neuronview

import android.content.Context
import android.os.Build
import android.os.Environment
import androidx.lifecycle.lifecycleScope
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.CoroutineScope
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
import kotlin.sequences.forEach
import kotlin.collections.mutableListOf
import androidx.appcompat.app.AppCompatActivity
import glm_.vec4.Vec4
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import kotlin.collections.mutableListOf

class HttpData(private val context: Context) {
    public var sampleList=mutableListOf<Sample>()
    public var neuronList=mutableListOf<Neuron>()

    // 协程作用域（与Activity生命周期绑定，自动管理任务）
    private val coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob())

    /**
     * 异步下载SWC文件并保存到设备
     * @param sampleId 样本ID（如192106）
     * @param neuronId 神经元ID（如001）
     * @param onSuccess 成功回调（返回文件保存路径，运行在UI线程）
     * @param onFailure 失败回调（返回错误信息，运行在UI线程）
     */
    public fun fetchNeuronFile(
        sampleId: String,
        neuronId: String,
        onSuccess: (String) -> Unit, // 成功：返回文件路径
        onFailure: (String) -> Unit  // 失败：返回错误信息
    ) {
        // 1. 启动协程，在IO线程执行异步操作
        coroutineScope.launch(Dispatchers.IO) {
            try {
                // 6. 定义保存路径（适配不同Android版本）
                val saveDir =
                    // Android 10+：使用应用私有目录（无需权限）
                    context.getExternalFilesDir(null)?.absolutePath ?: run {
                        withContext(Dispatchers.Main) {
                            onFailure("无法获取存储目录")
                        }
                        return@launch
                    }

                // 创建目录（若不存在）
                val dirFile = File("$saveDir/$sampleId")
                if (!dirFile.exists() && !dirFile.mkdirs()) {
                    withContext(Dispatchers.Main) {
                        onFailure("无法创建存储目录")
                    }
                    return@launch
                }

                    // 7. 定义文件名（格式：sampleId_neuronId.swc）
                val fileName = neuronId
                val saveFile = File("$saveDir/$sampleId", fileName)
                if (!saveFile.exists()) {
                    // 2. 构建请求URL（拼接参数）
                    val urlString =
                        "http://bap.cebsit.ac.cn/neuronbrowser/api/user/getSWC?sampleid=$sampleId&&neuronid=$neuronId"
                    val url = URL(urlString)
                    val connection = url.openConnection() as HttpURLConnection

                    // 3. 配置网络请求
                    connection.requestMethod = "GET"
                    connection.connectTimeout = 4000 // 15秒连接超时
                    connection.readTimeout = 4000    // 30秒读取超时

                    // 4. 检查响应状态（200=成功）
                    if (connection.responseCode != HttpURLConnection.HTTP_OK) {
                        // 失败：切换到UI线程回调错误信息
                        withContext(Dispatchers.Main) {
                            onFailure("请求失败，状态码：${connection.responseCode}")
                        }
                        return@launch
                    }

                    // 5. 获取文件输入流
                    val inputStream: InputStream = connection.inputStream


                    // 8. 写入文件（IO操作，在后台执行）
                    val outputStream = FileOutputStream(saveFile)
                    val buffer = ByteArray(4096) // 缓冲区
                    var bytesRead: Int
                    while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                        outputStream.write(buffer, 0, bytesRead)
                    }
                    // 9. 关闭资源
                    outputStream.flush()
                    outputStream.close()

                    inputStream.close()
                    connection.disconnect()
                }
                // 10. 成功：切换到UI线程回调文件路径
                withContext(Dispatchers.Main) {
                    onSuccess(saveFile.absolutePath)
                }

            } catch (e: Exception) {
                // 捕获所有异常（网络错误、文件读写错误等）
                e.printStackTrace()
                withContext(Dispatchers.Main) {
                    onFailure("下载失败：${e.message ?: "未知错误"}")
                }
            }
        }
    }
    fun cancelAllRequests(){
        coroutineScope.coroutineContext.cancel()
    }
    public fun fetchNeuronData(adapter: NeuronAdapter,sample:Sample){
        coroutineScope.launch {
            try {
                // 调用挂起函数获取数据
                val result = getNeuronList(sample.sampleid);
                if (result != null) {
                    // 解析JSON数据
                    val neurons = parseNeuronJson(result)
                    neurons.forEach { neuron -> neuron.color=Vec4((0..255).random(),(0..255).random(),(0..255).random(),255) }
                    // 更新UI
                    neuronList.addAll(neurons)
                    adapter.notifyDataSetChanged()
                } else {
//                    showToast("获取数据失败")
                }
            } catch (e: Exception) {
                e.printStackTrace()
//                showToast("网络请求出错: ${e.message}")
            } finally {
                // 隐藏加载进度
            }
        }
    }
    public fun fetchSampleData(adapter: SampleAdapter,originSample:MutableList<Sample>){
        coroutineScope.launch {
            try {
                // 调用挂起函数获取数据
                val result = getSampleList();
                if (result != null) {
                    // 解析JSON数据
                    val samples = parseSampleJson(result)
                    // 更新UI
                    sampleList.clear()
                    sampleList.addAll(samples)
                    originSample.addAll((samples))
                    adapter.notifyDataSetChanged()
                } else {
//                    showToast("获取数据失败")
                }
            } catch (e: Exception) {
                e.printStackTrace()
//                showToast("网络请求出错: ${e.message}")
            } finally {
                // 隐藏加载进度`
            }
        }
    }
    private fun parseNeuronJson(json: String): List<Neuron> {
        try {
            // 使用Gson解析JSON数组
            val type = object : TypeToken<List<Neuron>>() {}.type
            return Gson().fromJson(json, type)
        } catch (e: Exception) {
            e.printStackTrace()
            // 解析失败时返回空列表
            return emptyList()
        }
    }
    private fun parseSampleJson(json: String): List<Sample> {
        try {
            // 使用Gson解析JSON数组
            val type = object : TypeToken<List<Sample>>() {}.type
            return Gson().fromJson(json, type)
        } catch (e: Exception) {
            e.printStackTrace()
            // 解析失败时返回空列表
            return emptyList()
        }
    }
    private suspend fun getNeuronList(sampleid:String):String?{
        return withContext(Dispatchers.IO) {
            val url = URL("http://bap.cebsit.ac.cn/neuronbrowser/api/user/selectNeurons?id=$sampleid")
            val connection = url.openConnection() as HttpURLConnection

            try {
                connection.requestMethod = "GET"
                connection.connectTimeout = 8000
                connection.readTimeout = 8000

                val responseCode = connection.responseCode
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    val reader = BufferedReader(InputStreamReader(connection.inputStream))
                    val response = StringBuilder()

                    reader.useLines { lines ->
                        lines.forEach { line ->
                            response.append(line)
                        }
                    }

                    response.toString()
                } else {
                    throw Exception("HTTP错误: $responseCode")
                }
            } catch (e: Exception) {
                e.printStackTrace()
                null
            } finally {
                connection.disconnect()
            }
        }
    }
    private suspend fun getSampleList(): String? {
        return withContext(Dispatchers.IO) {
            val url = URL("http://bap.cebsit.ac.cn/neuronbrowser/api/user/selectSample?sample_id=all")
            val connection = url.openConnection() as HttpURLConnection

            try {
                connection.requestMethod = "GET"
                connection.connectTimeout = 8000
                connection.readTimeout = 8000

                val responseCode = connection.responseCode
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    val reader = BufferedReader(InputStreamReader(connection.inputStream))
                    val response = StringBuilder()

                    reader.useLines { lines ->
                        lines.forEach { line ->
                            response.append(line)
                        }
                    }

                    response.toString()
                } else {
                    throw Exception("HTTP错误: $responseCode")
                }
            } catch (e: Exception) {
                e.printStackTrace()
                null
            } finally {
                connection.disconnect()
            }
        }
    }
}